package com.godyao.mall.order.mq.listener;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.godyao.mall.order.mq.config.DelayedRabbitMqConfig;
import com.godyao.mall.order.mq.config.RabbitMqConfig;
import com.godyao.mall.order.mq.msg.SeckillMessage;
import com.godyao.mall.order.service.IOrderService;
import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.amqp.core.*;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;


/**
 * @author godyao
 * @date 2022/4/3
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class SeckillRabbitListener {

    private final IOrderService orderService;

    /**
     * 监听秒杀队列，将购买信息生产订单
     * @param message 消息 其中包含消息头、消息体
     * @param channel 管道，用于ack消息
     * @param deliveryTag 消息的唯一标识 消息表的主键id
     */
    @SneakyThrows
    @RabbitListener(queues = {RabbitMqConfig.QUEUE_NAME})
    public void consumeSeckillQueue(Message message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        final String data = new String(message.getBody());
        log.info("接收到一条消息，内容为：{},唯一ID为：{}", data, deliveryTag);
        final SeckillMessage seckillMessage = new ObjectMapper().readValue(data, SeckillMessage.class);
        // 执行业务逻辑
        orderService.makeOrder(seckillMessage);
        try {
            // 手动确认消息
            //multiple：为了减少网络流量，手动确认可以被批处理，
            // 当该参数为 true 时，则可以一次性确认 delivery_tag 小于等于传入值的所有消息
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("处理秒杀订单消息失败：{}", e.getMessage());
        }
    }

    @RabbitListener(queues = {DelayedRabbitMqConfig.DELAYED_QUEUE_NAME})
    public void consumeDelayQueue(String data, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        log.debug("接收到一条消息，内容为：{},唯一ID为：{}", data, deliveryTag);
        long orderId = Long.valueOf(data);
        // 执行业务逻辑
        orderService.checkOrderStatus(orderId);
        try {
            // 手动确认消息
            //multiple：为了减少网络流量，手动确认可以被批处理，
            // 当该参数为 true 时，则可以一次性确认 delivery_tag 小于等于传入值的所有消息
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("处理超时订单消息失败：{}", e.getMessage());
        }
    }


}
